//============================================================================
// Copyright (C) 2010 Brett R. Jones
// All Rights Reserved
//
// You may redistribute and/or modify for non commercial and commercial uses
// provided this copyright notice remains in place and is not modified
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

// android specific code
#ifdef ANDROID_PLATFORM
#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include "DtwGame.h"

#include <VxIrrLib/GameGlobals.h>

//extern int importGLInit();
//extern void importGLDeinit();

namespace
{
	JavaVM * g_oJavaVM;
}

extern "C"
{
// declarations for native functions called from java
//! initialize
jint Java_com_roguetreasure_destroytheworld_VxFileUtil_nativeInit( JNIEnv*  env, jobject  thiz, jstring strExternalStorageDir, jboolean supportsGLES2 );
//! resize window
void Java_com_roguetreasure_destroytheworld_DestroyWorldRenderer_nativeResize( JNIEnv*  env, jobject  thiz, jint w, jint h );
//! called to pause the render loop
void Java_com_roguetreasure_destroytheworld_DestroyWorldGLSurfaceView_nativePause( JNIEnv*  env, jobject  thiz );
//! called to render the next frame
jint Java_com_roguetreasure_destroytheworld_DestroyWorldRenderer_nativeRender( JNIEnv*  env, jobject  thiz );
//! called when game window is being destroyed
void Java_com_roguetreasure_destroytheworld_DestroyWorldRenderer_nativeDone( JNIEnv*  env, jobject  thiz );
//! called with touch events
void Java_com_roguetreasure_destroytheworld_DestroyWorldGLSurfaceView_nativeTouchEvent(JNIEnv*  env, jobject  thiz, jint iEventType, jint f32PosX, jint f32PosY);
//! called with orientation events
void Java_com_roguetreasure_destroytheworld_SensorMgr_nativeOrientationEvent( JNIEnv*  env, jobject  thiz, jfloat f32PosX, jfloat f32PosY, jfloat f32PosZ );
//! called to pause game
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGamePause( JNIEnv*  env, jobject  thiz );
//! called to resume game
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGameResume( JNIEnv*  env, jobject  thiz );
//! called to restart game
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGameRestart( JNIEnv*  env, jobject  thiz );
//! called when app is about to exit
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGameShutdown( JNIEnv*  env, jobject  thiz );
//! called when app is put to sleep
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeAppSleep( JNIEnv*  env, jobject  thiz );
//! called when app is woke
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeAppResume( JNIEnv*  env, jobject  thiz );

}
JavaVM * GetJavaVM()
{
	return g_oJavaVM;
}

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    log_msg( 0, "Dtw:JNI_OnLoad called");
    JNIEnv *env;
    g_oJavaVM = vm;
    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
    {
    	log_msg( 0, "Failed to get the environment using GetEnv()");
    	vx_assert( false );
        return -1;
    }
    return JNI_VERSION_1_4;
}

extern "C"
{

//----------------------------------------------------------------------------
//! initialize
jint Java_com_roguetreasure_destroytheworld_VxFileUtil_nativeInit( JNIEnv*  env, jobject  thiz, jstring strExternalStorageDir, jboolean supportsGLES2 )
{
	log_msg( 0, "Native Dtw: Got nativeInit\n");
	SetEnableGLES2( (bool)supportsGLES2 );
	//Get the characters from the jstring
	const char * pExternStorageDir = env->GetStringUTFChars( strExternalStorageDir, 0 );
	g_poGameMgr = new DtwGameMgr( pExternStorageDir );
	bool dirExists = VxDirectoryExists( pExternStorageDir );

    env->ReleaseStringUTFChars( strExternalStorageDir, pExternStorageDir );

	//if( false == importGLInit() )
	//{
	//	log_msg( LOG_ERROR, "Native Dtw: nativeInit ERROR could not load EGLES 3D Library\n" );
	//}
    UpdateSystemTime();
	log_msg( 0, "Native Dtw: nativeInit done dir %s exists ? %d\n", GetGameAssetPath().c_str(), dirExists);
	return dirExists ? 0 : -1;
}

//----------------------------------------------------------------------------
//! resize window
void Java_com_roguetreasure_destroytheworld_DestroyWorldRenderer_nativeResize( JNIEnv*  env, jobject  thiz, jint w, jint h )
{
    UpdateSystemTime();
	if( NULL == g_poGameMgr )
	{
		log_msg( 0, "DestroyTheWorld init w=%d h=%d", w, h);
	    g_poGameMgr->Startup( 	NULL,
								w,
								h,
								NULL );
	}
	else
	{
		log_msg( 0, "DestroyTheWorld resize w=%d h=%d", w, h);
		g_poGameMgr->ResizeView( w, h );
	}
}

//----------------------------------------------------------------------------
//! called when game window is being destroyed
void Java_com_roguetreasure_destroytheworld_DestroyWorldRenderer_nativeDone( JNIEnv*  env, jobject  thiz )
{
    log_msg( 0, "DestroyTheWorld Shutdown");
    UpdateSystemTime();
    //appDeinit();
	if( NULL != g_poGameMgr )
	{
		g_poGameMgr->Shutdown();
		delete g_poGameMgr;
		g_poGameMgr = NULL;
	}
    //importGLDeinit();
}

//----------------------------------------------------------------------------
//! called to pause the render loop
void Java_com_roguetreasure_destroytheworld_DestroyWorldGLSurfaceView_nativePause( JNIEnv*  env, jobject  thiz )
{
    UpdateSystemTime();
	g_poGameMgr->TogglePaused();
}

//----------------------------------------------------------------------------
//! called to render the next frame
jint Java_com_roguetreasure_destroytheworld_DestroyWorldRenderer_nativeRender( JNIEnv*  env, jobject  thiz )
{
    UpdateSystemTime();
    //log_msg( 0, "DestroyTheWorld: Native Render %ll", s64TimeMs);
	if( g_poGameMgr )
	{
		if( g_poGameMgr->IsShutdownRequested())
		{
			return -3;
		}
		return (jint)g_poGameMgr->UpdateGame( g_u32ElapsedTimeMs );
	}
	return -2;
}

//----------------------------------------------------------------------------
//! called with touch events
void Java_com_roguetreasure_destroytheworld_DestroyWorldGLSurfaceView_nativeTouchEvent(JNIEnv*  env, jobject  thiz, jint iEventType, jint f32PosX, jint f32PosY)
{
    UpdateSystemTime();
	if( g_poGameMgr )
	{
		//log_msg( 0, "DestroyTheWorld: Touch Event %d X=%d, Y=%d\n", iEventType, f32PosX, f32PosY );
		// fake like it was mouse input
		switch( iEventType )
		{
		case E_TOUCH_ACTION_DOWN:
			g_poGameMgr->HandleMouseEvent( eMouseButtonLeft, eMouseEventDown, f32PosX, f32PosY  );
			break;
		case E_TOUCH_ACTION_MOVE:
			g_poGameMgr->HandleMouseEvent( eMouseButtonNone, eMouseEventMove, f32PosX, f32PosY  );
			break;
		//E_TOUCH_ACTION_UP		= 1,
		default:
			g_poGameMgr->HandleMouseEvent( eMouseButtonLeft, eMouseEventUp, f32PosX, f32PosY  );
		}
		//log_msg( 0, "DestroyTheWorld: Touch Event done\n" );
	}
}

//----------------------------------------------------------------------------
//! called with orientation events
void Java_com_roguetreasure_destroytheworld_SensorMgr_nativeOrientationEvent( JNIEnv*  env, jobject  thiz,  jfloat f32PosX, jfloat f32PosY, jfloat f32PosZ  )
{
    UpdateSystemTime();
	if( g_poGameMgr )
	{
		//log_msg( 0, "DestroyTheWorld: Sensor Event %3.2f %3.2f, %3.2f", f32PosX, f32PosY, f32PosZ );
		g_poGameMgr->HandleOrientationEvent( f32PosX, f32PosY, f32PosZ  );
	}
}

//----------------------------------------------------------------------------
//! called to pause game
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGamePause( JNIEnv*  env, jobject  thiz )
{
	log_msg( 0, "DestroyTheWorld: game pause\n" );
    UpdateSystemTime();
	if( g_poGameMgr )
	{
		g_poGameMgr->OnGamePause();
	}
}

//----------------------------------------------------------------------------
//! called to resume game
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGameResume( JNIEnv*  env, jobject  thiz )
{
	log_msg( 0, "DestroyTheWorld: game resume\n" );
	UpdateSystemTime();
	if( g_poGameMgr )
	{
		g_poGameMgr->HandleResume();
	}
}

//----------------------------------------------------------------------------
//! called when application is put to sleep
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeAppSleep( JNIEnv*  env, jobject  thiz )
{
	log_msg( 0, "DestroyTheWorld: game app sleep\n" );
    UpdateSystemTime();
	if( g_poGameMgr )
	{
		g_poGameMgr->OnAppSleep();
	}
}

//----------------------------------------------------------------------------
//! called when application is woke
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeAppResume( JNIEnv*  env, jobject  thiz )
{
	log_msg( 0, "DestroyTheWorld: game app resume\n" );
	UpdateSystemTime();
	if( g_poGameMgr )
	{
		g_poGameMgr->OnAppResume(g_u32ElapsedTimeMs);
	}
}

//----------------------------------------------------------------------------
//! called to restart game
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGameRestart( JNIEnv*  env, jobject  thiz )
{
	log_msg( 0, "DestroyTheWorld: game restart start\n" );
	UpdateSystemTime();
	if( g_poGameMgr )
	{
		g_poGameMgr->OnGameResume();
		//g_poGameMgr->HandleRestart();
	}
}

//----------------------------------------------------------------------------
//! called when app is about to exit
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeGameShutdown( JNIEnv*  env, jobject  thiz )
{
	//UpdateSystemTime();
	if( g_poGameMgr )
	{
		log_msg( 0, "DestroyTheWorld: game shutdown start\n" );
		g_poGameMgr->Shutdown();
		log_msg( 0, "DestroyTheWorld: game shutdown done\n" );
	}
}

//----------------------------------------------------------------------------
//! called when cut scene movie has finished playing
void Java_com_roguetreasure_destroytheworld_GameInterface_nativeMovieDone( JNIEnv*  env, jobject  thiz )
{
	log_msg( 0, "DestroyTheWorld: Movie done\n" );
	UpdateSystemTime();
	// TODO move game from cut scene to next state
}

}// extern C
#endif // ANDROID_PLATFORM
